package datamining.miner.general;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;

import datamining.sequence.Sequence;
import de.parsemis.miner.general.GraphBasedFragment;

/**
 * <p>
 * 创建于 2012-12-2 下午10:02:38
 * 
 * @author xujinghu (jinghuxu@nudt.edu.cn) <br>
 *         Copyright 2012 xujinghu <br>
 *         Lisence: Apache
 */
public class SequenceFragment<ItemType> implements Fragment<ItemType> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private transient SequenceFragment<ItemType> next;
	private transient Collection<Embedding<ItemType>> embeddings;//序列映射关系
	private BitSet sequenceSet;//父序列编号集合
	private Sequence<ItemType> fragment;//子序列
	private Frequency freq;

	/**
	 * 初始化Fragment
	 * 
	 * @param freq
	 *                此fragment的初始频繁度
	 * @param fragment
	 *                代表的序列
	 * @param sequenceSet
	 *                此fragment出现的序列indexes
	 * @param storeEmbeddings
	 *                是否采用embedding搜索
	 */
	public SequenceFragment(final Frequency freq,
			final Sequence<ItemType> fragment,
			final BitSet sequenceSet, final boolean storeEmbeddings) {
		this.fragment = fragment;
		this.sequenceSet = sequenceSet;
		this.freq = freq;

		if (storeEmbeddings) {
			embeddings = new ArrayList<Embedding<ItemType>>();
		}
	}

	@Override
	public boolean add(Embedding<ItemType> e) {
		if (fragment == null) {
			fragment = e.getSubSequence();
		}
		if (embeddings != null) {
			embeddings.add(e);
		}
		this.add(e.getIndexedSequence());
		return true;
	}

	@Override
	public void add(IndexedSequence<ItemType> sequence)
			throws UnsupportedOperationException {
		final int idx = sequence.getIndex();
		if (sequenceSet.get(idx)) {
			return;
		}
		sequenceSet.set(idx);
		freq.add(sequence.frequency());
	}

	@Override
	public boolean addAll(Collection<? extends Embedding<ItemType>> c) {
		return embeddings().addAll(c);
	}

	@Override
	public void clear() {
		sequenceSet.clear();
		embeddings().clear();
		freq.sub(freq);
		fragment = null;
	}

	@Override
	public boolean contains(Object o) {
		return embeddings().contains(o);
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		return embeddings().containsAll(c);
	}

	@Override
	public Fragment<ItemType> copy() {
		return new SequenceFragment<ItemType>(freq.clone(),
				fragment.clone(), (BitSet) sequenceSet.clone(), embeddings != null);
	}

	@Override
	public Iterator<IndexedSequence<ItemType>> dbIterator() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @author xujinghu
	 * @date 2012-12-9上午11:15:28
	 * @return 所有此fragment的出现
	 */
	private final Collection<Embedding<ItemType>> embeddings() {
		if (embeddings == null) {
			return new ArrayList<Embedding<ItemType>>();
		}
		return embeddings;
	}

	@Override
	public Frequency frequency() {
		return freq;
	}

	@Override
	public Collection<Embedding<ItemType>> getEmbeddings() {
		return embeddings;
	}

	@Override
	public boolean isEmpty() {
		return size() == 0;
	}

	@Override
	public Iterator<Embedding<ItemType>> iterator() {
		return embeddings().iterator();
	}

	@Override
	public boolean remove(Object o) {
		throw new UnsupportedOperationException(
				"remove is not yet supported for SequenceFragment");
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		throw new UnsupportedOperationException(
				"removeAll is not yet supported for SequenceFragment");
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		throw new UnsupportedOperationException(
				"retainAll is not yet supported for SequenceFragment");
	}

	@Override
	public int size() {
		return embeddings.size();
	}

	@Override
	public Object[] toArray() {
		return toArray(new Object[size()]);
	}

	@Override
	public <T> T[] toArray(T[] a) {
		int i = -1;
		for (final T emb : (Collection<T>) embeddings()) {
			a[++i] = emb;
		}
		return a;
	}

	@Override
	public Sequence<ItemType> toSequence() {
		return fragment;
	}

	public String toString(){
		return fragment.toString();
	}
}
